/**
 * 浏览器调试管理器（简化版）
 *
 * 提供非headless的Playwright浏览器实例，用于网页调试
 * 支持多视口、深浅色主题、持久化会话管理
 * 使用简化的活跃页面检测策略：返回最后一个页面
 */

import os from 'os';
import path from 'path';
import { chromium, type Browser, type BrowserContext, type Page } from 'playwright';
import { createChildLogger } from '../../utils/logger.js';

const logger = createChildLogger('BrowserManager');

/**
 * 视口配置
 */
export const VIEWPORT_PRESETS = {
  desktop: { width: 1440, height: 900 },
  tablet: { width: 768, height: 1024 },
  mobile: { width: 390, height: 844 },
} as const;

export type ViewportType = keyof typeof VIEWPORT_PRESETS;
export type ThemeType = 'light' | 'dark';
export type BrowserMode = 'headed' | 'headless';

/**
 * 浏览器启动配置
 */
export interface BrowserLaunchConfig {
  mode?: BrowserMode;
  devtools?: boolean;
  maximized?: boolean;
}

/**
 * 浏览器上下文配置
 */
export interface BrowserContextConfig {
  viewport: ViewportType;
  theme: ThemeType;
  userAgent?: string;
  locale?: string;
}

/**
 * 截图选项
 */
export interface ScreenshotOptions {
  /** 截图类型：完整页面 or 视口 */
  type?: 'viewport' | 'fullpage';
  /** CSS选择器，截取特定元素 */
  selector?: string;
  /** 输出路径，默认临时目录 */
  path?: string;
  /** 图片质量 (0-100) */
  quality?: number;
  /** 等待时间（毫秒） */
  waitMs?: number;
}

/**
 * 页面性能信息
 */
export interface PerformanceInfo {
  url: string;
  title: string;
  loadTime: number;
  domNodes: number;
  networkRequests: number;
  consoleMessages: string[];
}

/**
 * 浏览器管理器（简化版）
 * 使用 "最后一个页面" 策略来检测活跃页面
 */
export class BrowserManager {
  private browser: Browser | null = null;
  private contexts: Map<string, BrowserContext> = new Map();
  private isStarted = false;

  // 浏览器启动配置
  private launchConfig: BrowserLaunchConfig = {
    mode: 'headed',
    devtools: false,
    maximized: false,
  };

  // 代理配置（Playwright仅支持在 launch 时设置代理）
  private proxyConfig: {
    server: string; // e.g. http://127.0.0.1:7890 or socks5://127.0.0.1:1080
    username?: string;
    password?: string;
    bypass?: string; // e.g. localhost,127.0.0.1
  } | null = null;

  constructor() {
    // 监听进程退出，确保资源清理
    process.on('SIGINT', () => this.close());
    process.on('SIGTERM', () => this.close());
  }

  /**
   * 启动浏览器
   */
  async start(config?: BrowserLaunchConfig): Promise<void> {
    // 如果提供了新配置，更新配置
    if (config) {
      this.launchConfig = { ...this.launchConfig, ...config };
    }

    if (this.isStarted && this.browser) {
      logger.info('Browser already started');
      return;
    }

    try {
      const modeText = this.launchConfig.mode === 'headless' ? 'headless' : 'headed';
      logger.info(`Starting ${modeText} Chromium browser...`);

      // 自动从环境变量读取代理（若尚未通过API设置）
      if (!this.proxyConfig) {
        const envProxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
        const noProxy = process.env.NO_PROXY;
        if (envProxy) {
          this.proxyConfig = { server: envProxy, bypass: noProxy || undefined };
          logger.info('Using proxy from environment variables', {
            server: envProxy,
            bypass: noProxy,
          });
        }
      }

      // 构建启动参数
      const args = [
        '--disable-web-security', // 允许跨域调试
        '--disable-features=VizDisplayCompositor', // 提高兼容性
      ];

      // 根据配置添加参数
      if (this.launchConfig.maximized && this.launchConfig.mode === 'headed') {
        args.push('--start-maximized');
      }

      this.browser = await chromium.launch({
        headless: this.launchConfig.mode === 'headless',
        devtools: this.launchConfig.devtools && this.launchConfig.mode === 'headed', // headless模式下不开devtools
        args,
        ...(this.proxyConfig ? { proxy: { ...this.proxyConfig } as any } : {}),
      });

      this.isStarted = true;
      logger.info(
        `✅ Browser started successfully in ${modeText} mode${
          this.launchConfig.devtools ? ' with DevTools' : ''
        }${this.proxyConfig ? ' with proxy' : ''}`
      );

      // 监听浏览器关闭事件
      this.browser.on('disconnected', () => {
        logger.info('Browser disconnected');
        this.cleanup();
      });
    } catch (error) {
      logger.error('Failed to start browser:', error);
      throw error;
    }
  }

  /**
   * 重启浏览器
   */
  async restart(config?: BrowserLaunchConfig): Promise<void> {
    logger.info('Restarting browser...');
    await this.close();
    await this.start(config);
  }

  /**
   * 获取或创建浏览器上下文
   */
  async getContext(config: BrowserContextConfig): Promise<BrowserContext> {
    if (!this.browser) {
      await this.start();
    }

    const contextKey = `${config.viewport}-${config.theme}`;
    let context = this.contexts.get(contextKey);

    if (!context) {
      logger.info(`Creating new context: ${contextKey}`);

      const viewport = VIEWPORT_PRESETS[config.viewport];

      context = await this.browser!.newContext({
        viewport,
        userAgent: config.userAgent,
        locale: config.locale || 'zh-CN',
        colorScheme: config.theme,
        deviceScaleFactor: config.viewport === 'mobile' ? 2 : 1,
        hasTouch: config.viewport === 'mobile',
        isMobile: config.viewport === 'mobile',
      });

      // 注入主题控制脚本
      await context.addInitScript(`
        // 设置主题数据属性
        function applyTheme() {
          document.documentElement.setAttribute('data-theme', '${config.theme}');
          document.documentElement.setAttribute('data-viewport', '${config.viewport}');
          
          // 注入全局调试对象
          window.__DEBUG__ = {
            theme: '${config.theme}',
            viewport: '${config.viewport}',
            timestamp: Date.now()
          };

          // 如果是深色主题，尝试设置页面的默认颜色方案
          if ('${config.theme}' === 'dark') {
            if (document.body) {
              document.body.style.backgroundColor = '#121212';
              document.body.style.color = '#ffffff';
            }
          }
        }
        
        // 立即执行
        applyTheme();
        
        // DOM加载后再次确保设置
        if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', applyTheme);
        }
      `);

      this.contexts.set(contextKey, context);
    }

    return context;
  }

  /**
   * 获取当前活跃的页面
   * 使用简化策略：返回 browserContext.pages() 的最后一个页面
   * 这通常是最近创建或激活的页面
   */
  getCurrentActiveTab(): Page | null {
    if (!this.browser) {
      return null;
    }

    // 获取所有上下文中的页面
    const contexts = this.browser.contexts();
    let allPages: Page[] = [];

    for (const context of contexts) {
      const pages = context.pages().filter(page => !page.isClosed());
      allPages.push(...pages);
    }

    if (allPages.length === 0) {
      return null;
    }

    // 返回最后一个页面，这通常是最近创建或激活的页面
    return allPages[allPages.length - 1] || null;
  }

  /**
   * 获取或创建页面
   */
  async getPage(config: BrowserContextConfig): Promise<Page> {
    const context = await this.getContext(config);

    // 首先尝试获取当前活跃的页面
    const currentActivePage = this.getCurrentActiveTab();

    // 检查活跃页面是否属于正确的上下文
    if (currentActivePage && !currentActivePage.isClosed()) {
      const pageContext = currentActivePage.context();
      if (pageContext === context) {
        // 确保视口配置正确
        const viewport = VIEWPORT_PRESETS[config.viewport];
        const currentViewport = currentActivePage.viewportSize();

        if (
          !currentViewport ||
          currentViewport.width !== viewport.width ||
          currentViewport.height !== viewport.height
        ) {
          await currentActivePage.setViewportSize(viewport);
          logger.info(`Active page viewport updated to: ${viewport.width}x${viewport.height}`);
        }

        return currentActivePage;
      }
    }

    // 如果没有合适的活跃页面，创建新页面
    logger.info(`Creating new page for context: ${config.viewport}-${config.theme}`);

    const newPage = await context.newPage();

    // 设置视口大小
    const viewport = VIEWPORT_PRESETS[config.viewport];
    await newPage.setViewportSize(viewport);

    // 设置默认超时
    newPage.setDefaultTimeout(30000);
    newPage.setDefaultNavigationTimeout(30000);

    logger.info(
      `Page created with viewport: ${viewport.width}x${viewport.height}, theme: ${config.theme}`
    );

    return newPage;
  }

  /**
   * 截图
   */
  async screenshot(config: BrowserContextConfig, options: ScreenshotOptions = {}): Promise<string> {
    const page = await this.getPage(config);

    // 等待页面稳定
    if (options.waitMs) {
      await page.waitForTimeout(options.waitMs);
    }

    // 生成输出路径
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const filename = `screenshot-${config.viewport}-${config.theme}-${timestamp}.png`;
    const outputPath = options.path || path.join(os.tmpdir(), filename);

    try {
      if (options.selector) {
        // 截取特定元素
        const element = await page.waitForSelector(options.selector, { state: 'visible' });
        await element.screenshot({ path: outputPath, quality: options.quality });
      } else {
        // 截取页面
        await page.screenshot({
          path: outputPath,
          fullPage: options.type === 'fullpage',
          quality: options.quality,
        });
      }

      logger.info(`Screenshot saved: ${outputPath}`);
      return outputPath;
    } catch (error) {
      logger.error('Screenshot failed:', error);
      throw error;
    }
  }

  /**
   * 执行JavaScript
   */
  async evaluateScript(config: BrowserContextConfig, script: string): Promise<any> {
    const page = await this.getPage(config);

    try {
      const result = await page.evaluate(script);
      logger.info(`Script executed successfully`);
      return result;
    } catch (error) {
      logger.error('Script execution failed:', error);
      throw error;
    }
  }

  /**
   * 获取页面信息（支持活跃页面）
   */
  async getPageInfo(
    config?: BrowserContextConfig & { useActiveTab?: boolean }
  ): Promise<PerformanceInfo & { isActiveTab?: boolean; lastActiveTime?: number }> {
    let targetPage: Page | null;

    if (config?.useActiveTab) {
      targetPage = this.getCurrentActiveTab();
      if (!targetPage) {
        throw new Error('No active page found');
      }
    } else if (config) {
      targetPage = await this.getPage(config);
    } else {
      // 默认使用当前活跃页面
      targetPage = this.getCurrentActiveTab();
      if (!targetPage) {
        throw new Error('No active page found');
      }
    }

    try {
      const url = targetPage.url();
      const title = await targetPage.title();

      // 获取性能指标
      const perfData = await targetPage.evaluate(() => {
        const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
        return {
          loadTime: nav ? nav.loadEventEnd - nav.startTime : 0,
          domNodes: document.querySelectorAll('*').length,
        };
      });

      // 获取网络请求数（近似）
      const networkRequests = await targetPage.evaluate(() => {
        return performance.getEntriesByType('resource').length;
      });

      // 获取控制台消息（简化版不实时监听）
      const consoleMessages: string[] = [];

      return {
        url,
        title,
        loadTime: perfData.loadTime,
        domNodes: perfData.domNodes,
        networkRequests,
        consoleMessages,
        isActiveTab: true, // 简化版总是标记为活跃
        lastActiveTime: Date.now(), // 简化版使用当前时间
      };
    } catch (error) {
      logger.error('Failed to get page info:', error);
      throw error;
    }
  }

  /**
   * 导航到指定URL
   */
  async navigateToUrl(
    url: string,
    config: BrowserContextConfig = { viewport: 'desktop', theme: 'light' },
    options: { waitForLoad?: boolean } = {}
  ): Promise<{ url: string; title: string }> {
    const page = await this.getPage(config);

    try {
      logger.info(`Navigating to: ${url}`);

      const waitUntil = options.waitForLoad !== false ? 'networkidle' : 'domcontentloaded';
      await page.goto(url, { waitUntil });

      const finalUrl = page.url();
      const title = await page.title();

      logger.info(`Navigation completed: ${title} (${finalUrl})`);
      return { url: finalUrl, title };
    } catch (error) {
      logger.error(`Navigation failed: ${error}`);
      throw error;
    }
  }

  /**
   * 设置代理
   */
  setProxy(config: {
    server: string;
    username?: string;
    password?: string;
    bypass?: string;
  }): void {
    if (this.isStarted) {
      throw new Error(
        'Cannot set proxy after browser has started. Restart browser to apply proxy settings.'
      );
    }
    this.proxyConfig = config;
    logger.info('Proxy configuration set:', { server: config.server, bypass: config.bypass });
  }

  /**
   * 清除代理
   */
  clearProxy(): void {
    if (this.isStarted) {
      throw new Error(
        'Cannot clear proxy after browser has started. Restart browser to apply changes.'
      );
    }
    this.proxyConfig = null;
    logger.info('Proxy configuration cleared');
  }

  /**
   * 获取代理状态
   */
  getProxyStatus(): { enabled: boolean; server?: string; bypass?: string } {
    if (this.proxyConfig) {
      return {
        enabled: true,
        server: this.proxyConfig.server,
        bypass: this.proxyConfig.bypass,
      };
    }
    return { enabled: false };
  }

  /**
   * 获取浏览器状态
   */
  getBrowserStatus(): {
    running: boolean;
    contexts: number;
    mode: BrowserMode;
    devtools: boolean;
    maximized: boolean;
  } {
    return {
      running: this.isStarted && !!this.browser && this.browser.isConnected(),
      contexts: this.contexts.size,
      mode: this.launchConfig.mode || 'headed',
      devtools: this.launchConfig.devtools || false,
      maximized: this.launchConfig.maximized || false,
    };
  }

  /**
   * 清理资源
   */
  private cleanup(): void {
    this.isStarted = false;
    this.browser = null;
    this.contexts.clear();
  }

  /**
   * 关闭浏览器
   */
  async close(): Promise<void> {
    if (this.browser) {
      logger.info('Closing browser...');
      await this.browser.close();
      this.cleanup();
      logger.info('✅ Browser closed successfully');
    }
  }

  // ===========================================
  // 下面是为了兼容原有 API 而添加的方法
  // ===========================================

  /**
   * 检查浏览器是否正在运行
   */
  isRunning(): boolean {
    return this.isStarted && !!this.browser && this.browser.isConnected();
  }

  /**
   * 获取浏览器模式信息
   */
  getBrowserMode(): {
    mode: BrowserMode;
    devtools: boolean;
    maximized: boolean;
  } {
    return {
      mode: this.launchConfig.mode || 'headed',
      devtools: this.launchConfig.devtools || false,
      maximized: this.launchConfig.maximized || false,
    };
  }

  /**
   * 设置浏览器模式（需要重启）
   */
  async setBrowserMode(config: BrowserLaunchConfig): Promise<{
    mode: BrowserMode;
    devtools: boolean;
    maximized: boolean;
  }> {
    // 更新配置
    this.launchConfig = { ...this.launchConfig, ...config };

    // 如果浏览器正在运行，需要重启
    if (this.isRunning()) {
      await this.restart(config);
    }

    return this.getBrowserMode();
  }

  /**
   * 导航到指定 URL（兼容方法）
   */
  async navigate(config: BrowserContextConfig, url: string): Promise<void> {
    await this.navigateToUrl(url, config);
  }

  /**
   * 等待指定事件
   */
  async waitFor(
    config: BrowserContextConfig,
    event: 'networkidle' | 'domcontentloaded'
  ): Promise<void> {
    const page = await this.getPage(config);

    if (event === 'networkidle') {
      await page.waitForLoadState('networkidle');
    } else if (event === 'domcontentloaded') {
      await page.waitForLoadState('domcontentloaded');
    }
  }

  /**
   * 注入 CSS
   */
  async injectCSS(config: BrowserContextConfig, css: string): Promise<void> {
    const page = await this.getPage(config);
    await page.addStyleTag({ content: css });
  }

  /**
   * 等待元素出现
   */
  async waitForElement(
    config: BrowserContextConfig,
    selector: string,
    options: {
      state?: 'visible' | 'hidden' | 'attached' | 'detached';
      timeout?: number;
    } = {}
  ): Promise<void> {
    const page = await this.getPage(config);
    await page.waitForSelector(selector, {
      state: options.state || 'visible',
      timeout: options.timeout || 30000,
    });
  }
}

// 单例实例
let instance: BrowserManager | null = null;

/**
 * 获取浏览器管理器单例
 */
export function getBrowserManager(): BrowserManager {
  if (!instance) {
    instance = new BrowserManager();
  }
  return instance;
}
